OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
pkt_sandesh_flow.cc
Go to the documentation of this file.
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>
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>
19 
20 static string InetRouteFlowMgmtKeyToString(uint16_t id,
21  InetRouteFlowMgmtKey *key) {
22  std::stringstream ss;
23  uint16_t plen = key->plen();
24  ss << id << PktSandeshFlow::kDelimiter;
25  ss << key->vrf_id() << PktSandeshFlow::kDelimiter;
26  ss << key->ip().to_string() << PktSandeshFlow::kDelimiter;
27  ss << plen;
28  return ss.str();
29 }
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 
168 
169 static void SetOneAclInfo(FlowAclInfo *policy, uint32_t action,
170  const MatchAclParamsList &acl_list) {
171  MatchAclParamsList::const_iterator it;
172  std::vector<FlowAclUuid> acl;
173 
174  for (it = acl_list.begin(); it != acl_list.end(); it++) {
175  FlowAclUuid f;
176  f.uuid = UuidToString(it->acl->GetUuid());
177  acl.push_back(f);
178  }
179  policy->set_acl(acl);
180  policy->set_action(action);
181 
182  std::vector<ActionStr> action_str_l;
183  for (it = acl_list.begin(); it != acl_list.end(); it++) {
184  FlowAction action_info = it->action_info;
185  action_info.action = action;
186  SetActionStr(action_info, action_str_l);
187  }
188  policy->set_action_str(action_str_l);
189 }
190 
191 static void SetAclInfo(SandeshFlowData &data, FlowEntry *fe) {
192  FlowAclInfo policy;
193 
194  SetOneAclInfo(&policy, fe->match_p().policy_action, fe->match_p().m_acl_l);
195  data.set_policy(policy);
196 
197  SetOneAclInfo(&policy, fe->match_p().out_policy_action,
198  fe->match_p().m_out_acl_l);
199  data.set_out_policy(policy);
200 
202  data.set_sg(policy);
203 
204  SetOneAclInfo(&policy, fe->match_p().sg_policy.out_action,
206  data.set_out_sg(policy);
207 
210  data.set_reverse_sg(policy);
211 
214  data.set_reverse_out_sg(policy);
215 
218  data.set_vrf_assign_acl(policy);
219 
220  FlowAction action_info;
221  action_info.action = fe->match_p().sg_policy.action_summary;
222  std::vector<ActionStr> action_str_l;
223  SetActionStr(action_info, action_str_l);
224  data.set_sg_action_summary(action_str_l);
225 
226  SetOneAclInfo(&policy, fe->match_p().mirror_action,
227  fe->match_p().m_mirror_acl_l);
228  data.set_mirror(policy);
229 
230  SetOneAclInfo(&policy, fe->match_p().out_mirror_action,
232  data.set_out_mirror(policy);
233 
234  SetOneAclInfo(&policy, fe->match_p().aps_policy.action,
235  fe->match_p().aps_policy.m_acl_l);
236  data.set_policy_set(policy);
237 
240  data.set_out_policy_set(policy);
241 
244  data.set_reverse_policy_set(policy);
245 
248  data.set_reverse_out_policy_set(policy);
249 
250  action_info.action = fe->match_p().aps_policy.action_summary;
251  action_str_l.clear();
252  SetActionStr(action_info, action_str_l);
253  data.set_aps_action_summary(action_str_l);
254 
255  SetOneAclInfo(&policy, fe->match_p().fwaas_policy.action,
257  data.set_fwaas_policy_set(policy);
258 
261  data.set_fwaas_out_policy_set(policy);
262 
265  data.set_fwaas_reverse_policy_set(policy);
266 
269  data.set_fwaas_reverse_out_policy_set(policy);
270 
271  action_info.action = fe->match_p().fwaas_policy.action_summary;
272  action_str_l.clear();
273  SetActionStr(action_info, action_str_l);
274  data.set_fwaas_action_summary(action_str_l);
275 
276  data.set_sg_rule_uuid(fe->sg_rule_uuid());
277  data.set_nw_ace_uuid(fe->nw_ace_uuid());
278 }
279 
281 
282 PktSandeshFlow::PktSandeshFlow(Agent *agent, FlowRecordsResp *obj,
283  std::string resp_ctx, std::string key):
284  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::PktFlowResponder")),
285  0), resp_obj_(obj), resp_data_(resp_ctx),
286  flow_iteration_key_(), key_valid_(false), delete_op_(false), agent_(agent),
287  partition_id_(0) {
288  if (key != agent_->NullString()) {
289  if (SetFlowKey(key)) {
290  key_valid_ = true;
291  }
292  }
293 }
294 
296 }
297 
298 void PktSandeshFlow::SetSandeshFlowData(std::vector<SandeshFlowData> &list,
299  FlowEntry *fe, const FlowExportInfo *info) {
300  SandeshFlowData data;
301  SET_SANDESH_FLOW_DATA(agent_, data, fe, info);
302  list.push_back(data);
303 }
304 
306  resp->set_context(resp_data_);
307  resp->set_more(false);
308  resp->Response();
309 }
310 
311 string PktSandeshFlow::GetFlowKey(const FlowKey &key, uint16_t partition_id) {
312  std::stringstream ss;
313  ss << partition_id << kDelimiter;
314  ss << key.nh << kDelimiter;
315  ss << key.src_port << kDelimiter;
316  ss << key.dst_port << kDelimiter;
317  ss << (uint16_t)key.protocol << kDelimiter;
318  ss << key.src_addr.to_string() << kDelimiter;
319  ss << key.dst_addr.to_string();
320  return ss.str();
321 }
322 
323 bool PktSandeshFlow::SetFlowKey(string key) {
324  using std::istringstream;
325 
326  const char ch = kDelimiter;
327  size_t n = std::count(key.begin(), key.end(), ch);
328  if (n != 6) {
329  return false;
330  }
331  std::stringstream ss(key);
332  string item, sip, dip;
333  uint32_t proto = 0;
334 
335  if (getline(ss, item, ch)) {
336  istringstream(item) >> partition_id_;
337  }
338  if (getline(ss, item, ch)) {
339  istringstream(item) >> flow_iteration_key_.nh;
340  }
341  if (getline(ss, item, ch)) {
342  istringstream(item) >> flow_iteration_key_.src_port;
343  }
344  if (getline(ss, item, ch)) {
345  istringstream(item) >> flow_iteration_key_.dst_port;
346  }
347  if (getline(ss, item, ch)) {
348  istringstream(item) >> proto;
349  }
350  if (getline(ss, item, ch)) {
351  sip = item;
352  }
353  if (getline(ss, item, ch)) {
354  dip = item;
355  }
356  boost::system::error_code ec;
357  flow_iteration_key_.src_addr = IpAddress::from_string(sip.c_str(), ec);
358  flow_iteration_key_.dst_addr = IpAddress::from_string(dip.c_str(), ec);
359  if (flow_iteration_key_.src_addr.is_v4()) {
361  } else if (flow_iteration_key_.src_addr.is_v6()) {
363  }
365  return true;
366 }
367 
369  FlowTable::FlowEntryMap::iterator it;
370  std::vector<SandeshFlowData>& list =
371  const_cast<std::vector<SandeshFlowData>&>(resp_obj_->get_flow_list());
372  int count = 0;
373  bool flow_key_set = false;
374 
376  FlowErrorResp *resp = new FlowErrorResp();
377  SendResponse(resp);
378  return true;
379  }
380 
381  FlowTable *flow_obj = agent_->pkt()->flow_table(partition_id_);
382 
383  if (delete_op_) {
384  for (int i =0; i < agent_->flow_thread_count(); i++){
385  flow_obj = agent_->pkt()->flow_table(i);
386  flow_obj->DeleteAll();
387  }
389  return true;
390  }
391 
392  if (key_valid_) {
393  it = flow_obj->flow_entry_map_.upper_bound(flow_iteration_key_);
394  } else {
395  FlowErrorResp *resp = new FlowErrorResp();
396  SendResponse(resp);
397  return true;
398  }
399 
400  while (it == flow_obj->flow_entry_map_.end() &&
402  flow_obj = agent_->pkt()->flow_table(partition_id_);
403  it = flow_obj->flow_entry_map_.begin();
404  }
405 
406  while (it != flow_obj->flow_entry_map_.end()) {
407  FlowEntry *fe = it->second;
408  FlowStatsCollector *fec = fe->fsc();
409  const FlowExportInfo *info = NULL;
410  if (fec) {
411  info = fec->FindFlowExportInfo(fe);
412  }
413  SetSandeshFlowData(list, fe, info);
414  ++it;
415  count++;
416  if (count == kMaxFlowResponse) {
417  if (it != flow_obj->flow_entry_map_.end()) {
418  resp_obj_->set_flow_key(GetFlowKey(fe->key(), partition_id_));
419  flow_key_set = true;
420 
421  } else {
422  FlowKey key;
423  resp_obj_->set_flow_key(GetFlowKey(key, ++partition_id_));
424  flow_key_set = true;
425  }
426  break;
427  }
428 
429  while (it == flow_obj->flow_entry_map_.end()) {
430  if (++partition_id_ < agent_->flow_thread_count()) {
431  flow_obj = agent_->pkt()->flow_table(partition_id_);
432  it = flow_obj->flow_entry_map_.begin();
433  if (it != flow_obj->flow_entry_map_.end()) {
434  break;
435  }
436  } else {
437  break;
438  }
439  }
440  }
441 
442  if (!flow_key_set) {
443  resp_obj_->set_flow_key(PktSandeshFlow::start_key);
444  }
445 
447  return true;
448 }
449 
451 
452 void NextFlowRecordsSet::HandleRequest() const {
453  Agent *agent = Agent::GetInstance();
454  FlowRecordsResp *resp = new FlowRecordsResp();
455  PktSandeshFlow *task = new PktSandeshFlow(agent, resp, context(),
456  get_flow_key());
458  scheduler->Enqueue(task);
459 }
460 
461 void FetchAllFlowRecords::HandleRequest() const {
462  Agent *agent = Agent::GetInstance();
463  FlowRecordsResp *resp = new FlowRecordsResp();
464  PktSandeshFlow *task = new PktSandeshFlow(agent, resp, context(),
467  scheduler->Enqueue(task);
468 }
469 
470 void DeleteAllFlowRecords::HandleRequest() const {
471  FlowRecordsResp *resp = new FlowRecordsResp();
472 
474  context(),
476  task->set_delete_op(true);
478  scheduler->Enqueue(task);
479 }
480 
481 void FetchFlowRecord::HandleRequest() const {
482  FlowKey key;
483  Agent *agent = Agent::GetInstance();
484  FlowTable *flow_obj = NULL;
485 
486  key.nh = get_nh();
487  boost::system::error_code ec;
488  key.src_addr = IpAddress::from_string(get_sip(), ec);
489  key.dst_addr = IpAddress::from_string(get_dip(), ec);
490  if (key.src_addr.is_v4()) {
491  key.family = Address::INET;
492  } else if (key.src_addr.is_v6()) {
493  key.family = Address::INET6;
494  }
495  key.src_port = (unsigned)get_src_port();
496  key.dst_port = (unsigned)get_dst_port();
497  key.protocol = get_protocol();
498 
499  FlowTable::FlowEntryMap::iterator it;
500  for (int i = 0; i < agent->flow_thread_count(); i++) {
501  flow_obj = agent->pkt()->flow_table(i);
502  it = flow_obj->flow_entry_map_.find(key);
503  if (it != flow_obj->flow_entry_map_.end())
504  break;
505  }
506 
507  SandeshResponse *resp;
508  if (flow_obj && it != flow_obj->flow_entry_map_.end()) {
509  FlowRecordResp *flow_resp = new FlowRecordResp();
510  FlowEntry *fe = it->second;
511  FlowStatsCollector *fec = fe->fsc();
512  const FlowExportInfo *info = NULL;
513  if (fec) {
514  info = fec->FindFlowExportInfo(fe);
515  }
516  SandeshFlowData data;
517  SET_SANDESH_FLOW_DATA(agent, data, fe, info);
518  flow_resp->set_record(data);
519  resp = flow_resp;
520  } else {
521  resp = new FlowErrorResp();
522  }
523 
524  resp->set_context(context());
525  resp->set_more(false);
526  resp->Response();
527 }
528 
529 // Sandesh interface to modify flow aging interval
530 // Intended for use in testing only
531 void FlowAgeTimeReq::HandleRequest() const {
532  Agent *agent = Agent::GetInstance();
533  uint32_t age_time = get_new_age_time();
534 
537 
538  FlowAgeTimeResp *resp = new FlowAgeTimeResp();
539  if (obj == NULL) {
540  goto done;
541  }
542  resp->set_old_age_time(obj->GetAgeTimeInSeconds());
543 
544  if (age_time && age_time != resp->get_old_age_time()) {
545  obj->UpdateAgeTimeInSeconds(age_time);
546  resp->set_new_age_time(age_time);
547  } else {
548  resp->set_new_age_time(resp->get_old_age_time());
549  }
550 done:
551  resp->set_context(context());
552  resp->set_more(false);
553  resp->Response();
554 }
555 
556 void FetchLinkLocalFlowInfo::HandleRequest() const {
557  LinkLocalFlowInfoResp *resp = new LinkLocalFlowInfoResp();
558  std::vector<LinkLocalFlowInfo> &list =
559  const_cast<std::vector<LinkLocalFlowInfo>&>
560  (resp->get_linklocal_flow_list());
561 
562  const FlowTable::LinkLocalFlowInfoMap &flow_map =
564  FlowTable::LinkLocalFlowInfoMap::const_iterator it = flow_map.begin();
565  while (it != flow_map.end()) {
566  LinkLocalFlowInfo info;
567  info.fd = it->first;
568  info.flow_index = it->second.flow_index;
569  info.source_addr = it->second.flow_key.src_addr.to_string();
570  info.dest_addr = it->second.flow_key.dst_addr.to_string();
571  info.protocol = it->second.flow_key.protocol;
572  info.source_port = it->second.flow_key.src_port;
573  info.dest_port = it->second.flow_key.dst_port;
574  info.timestamp = integerToString(UTCUsecToPTime(it->second.timestamp));
575  list.push_back(info);
576  ++it;
577  }
578 
579  resp->set_context(context());
580  resp->set_more(false);
581  resp->Response();
582 }
583 
585  std::vector<SandeshFlowData>& list =
586  const_cast<std::vector<SandeshFlowData>&>(resp_->get_flow_list());
587  int count = 0;
588  bool flow_key_set = false;
589 
591  FlowErrorResp *resp = new FlowErrorResp();
592  SendResponse(resp);
593  return true;
594  }
595 
596  FlowTable *flow_obj = agent_->pkt()->flow_table(partition_id_);
598  const FlowStatsCollectorObject *fsc_obj = fm->Find(proto_, port_);
599  if (!fsc_obj) {
600  FlowErrorResp *resp = new FlowErrorResp();
601  SendResponse(resp);
602  return true;
603  }
604 
605  FlowTable::FlowEntryMap::iterator it;
606  if (key_valid_) {
607  it = flow_obj->flow_entry_map_.upper_bound(flow_iteration_key_);
608  } else {
609  FlowErrorResp *resp = new FlowErrorResp();
610  SendResponse(resp);
611  return true;
612  }
613 
614  while (it == flow_obj->flow_entry_map_.end() &&
616  flow_obj = agent_->pkt()->flow_table(partition_id_);
617  it = flow_obj->flow_entry_map_.begin();
618  }
619 
620  while (it != flow_obj->flow_entry_map_.end()) {
621  FlowEntry *fe = it->second;
622  const FlowExportInfo *info = NULL;
623  if (fe->fsc()) {
624  info = fe->fsc()->FindFlowExportInfo(fe);
625  }
626  SetSandeshFlowData(list, fe, info);
627  ++it;
628  count++;
629  if (count == kMaxFlowResponse) {
630  if (it != flow_obj->flow_entry_map_.end()) {
631  std::ostringstream ostr;
632  ostr << proto_ << ":" << port_ << ":"
633  << GetFlowKey(fe->key(), partition_id_);
634  resp_->set_flow_key(ostr.str());
635  flow_key_set = true;
636  } else {
637  std::ostringstream ostr;
638  FlowKey key;
639  ostr << proto_ << ":" << port_ << ":"
640  << GetFlowKey(key, ++partition_id_);
641  resp_->set_flow_key(ostr.str());
642  flow_key_set = true;
643  }
644  break;
645  }
646 
647  while (it == flow_obj->flow_entry_map_.end()) {
648  if (++partition_id_ < agent_->flow_thread_count()) {
649  flow_obj = agent_->pkt()->flow_table(partition_id_);
650  it = flow_obj->flow_entry_map_.begin();
651  if (it != flow_obj->flow_entry_map_.end()) {
652  break;
653  }
654  } else {
655  break;
656  }
657  }
658 
659  }
660 
661  if (!flow_key_set) {
662  std::ostringstream ostr;
663  ostr << proto_ << ":" << port_ << ":" <<PktSandeshFlow::start_key;
664  resp_->set_flow_key(ostr.str());
665  }
667  return true;
668 }
669 
670 bool PktSandeshFlowStats::SetProto(string &key) {
671  size_t n = std::count(key.begin(), key.end(), ':');
672  if (n != 2) {
673  return false;
674  }
675  std::stringstream ss(key);
676  string item;
677  if (getline(ss, item, ':')) {
678  std::istringstream(item) >> proto_;
679  }
680  if (getline(ss, item, ':')) {
681  std::istringstream(item) >> port_;
682  }
683  if (getline(ss, item)) {
684  SetFlowKey(item);
685  }
686  return true;
687 }
688 
689 PktSandeshFlowStats::PktSandeshFlowStats(Agent *agent, FlowStatsCollectorRecordsResp *obj,
690  std::string resp_ctx, std::string key):
691  PktSandeshFlow(agent, NULL, resp_ctx, key), resp_(obj) {
692  if (key != agent_->NullString()) {
693  if (SetProto(key)) {
694  key_valid_ = true;
695  }
696  }
697 }
698 
699 void ShowFlowStatsCollector::HandleRequest() const {
700  Agent *agent = Agent::GetInstance();
701  FlowStatsCollectorRecordsResp *resp = new FlowStatsCollectorRecordsResp();
702 
703  std::ostringstream ostr;
704  ostr << get_protocol() << ":" << get_port() << ":" <<
706  PktSandeshFlowStats *task = new PktSandeshFlowStats(agent, resp, context(),
707  ostr.str());
709  scheduler->Enqueue(task);
710 }
711 
712 void NextFlowStatsRecordsSet::HandleRequest() const {
713  Agent *agent = Agent::GetInstance();
714  FlowStatsCollectorRecordsResp *resp = new FlowStatsCollectorRecordsResp();
715 
716  PktSandeshFlow *task = new PktSandeshFlowStats(agent, resp, context(),
717  get_flow_key());
719  scheduler->Enqueue(task);
720 }
721 
722 
723 void SandeshFlowTableInfoRequest::HandleRequest() const {
724  Agent *agent = Agent::GetInstance();
725  FlowProto *proto = agent->pkt()->get_flow_proto();
726  SandeshFlowTableInfoResp *resp = new SandeshFlowTableInfoResp();
727  resp->set_flow_count(proto->FlowCount());
728  resp->set_total_added(agent->stats()->flow_created());
729  resp->set_max_flows(agent->stats()->max_flow_count());
730  resp->set_total_deleted(agent->stats()->flow_aged());
731  std::vector<SandeshFlowTableInfo> info_list;
732  for (uint16_t i = 0; i < proto->flow_table_count(); i++) {
733  FlowTable *table = proto->GetTable(i);
734  SandeshFlowTableInfo info;
735  info.set_index(table->table_index());
736  info.set_count(table->Size());
737  info.set_total_add(table->free_list()->total_alloc());
738  info.set_total_del(table->free_list()->total_free());
739  info.set_freelist_count(table->free_list()->free_count());
740  info_list.push_back(info);
741  }
742  resp->set_table_list(info_list);
743  resp->set_context(context());
744  resp->set_more(false);
745  resp->Response();
746 }
748 
750  uint16_t *id) {
751  using std::istringstream;
752 
753  Agent *agent = Agent::GetInstance();
754  const char ch = PktSandeshFlow::kDelimiter;
755  size_t n = std::count(key.begin(), key.end(), ch);
756  if (n != 3) {
757  return NULL;
758  }
759  std::stringstream ss(key);
760  string item, ip_str;
761  uint32_t vrf_id = 0;
762  uint16_t plen = 0, mgr_id = 0;
763 
764  if (getline(ss, item, ch)) {
765  istringstream(item) >> mgr_id;
766  }
767  if (mgr_id >= agent->pkt()->flow_mgmt_manager_list().size()) {
768  return NULL;
769  }
770  *id = mgr_id;
771  if (getline(ss, item, ch)) {
772  istringstream(item) >> vrf_id;
773  }
774  if (getline(ss, item, ch)) {
775  ip_str = item;
776  }
777  if (getline(ss, item, ch)) {
778  istringstream(item) >> plen;
779  }
780  boost::system::error_code ec;
781  IpAddress ip = IpAddress::from_string(ip_str.c_str(), ec);
782  if (ec) {
783  return NULL;
784  }
785  InetRouteFlowMgmtKey* ret = new InetRouteFlowMgmtKey(vrf_id, ip, plen);
786  return ret;
787 }
788 
789 void FlowsPerInetRouteFlowMgmtKeyReq::HandleRequest() const {
790  FlowsPerInetRouteFlowMgmtKeyResp *resp= new
791  FlowsPerInetRouteFlowMgmtKeyResp();
792  resp->set_context(context());
793  resp->set_more(false);
794  std::vector<SandeshFlowData> &resp_list =
795  const_cast<std::vector<SandeshFlowData>&>(resp->get_flow_list());
796  Agent *agent = Agent::GetInstance();
797  uint16_t mgr_id = 0;
798  FlowMgmtManager *mgr = NULL;
800  &mgr_id);
801  if (!ikey) {
802  resp->Response();
803  return;
804  }
805  mgr = agent->pkt()->flow_mgmt_manager(mgr_id);
807  FlowMgmtEntry *entry = tree->Find(ikey);
808  delete ikey;
809  if (!entry) {
810  resp->Response();
811  return;
812  }
813  if (entry->Size() == 0) {
814  resp->Response();
815  return;
816  }
817  const FlowMgmtEntry::FlowList &flow_list = entry->flow_list();
818  FlowMgmtEntry::FlowList::const_iterator it = flow_list.begin();
819  while (it != flow_list.end()) {
820  const FlowMgmtKeyNode *node = &(*it);
821  FlowEntry *fe = node->flow_entry();
822  SandeshFlowData data;
823  const FlowExportInfo *info = NULL;
824  SET_SANDESH_FLOW_DATA(agent, data, fe, info);
825  resp_list.push_back(data);
826  it++;
827  }
828  resp->Response();
829 }
830 
831 void Inet4FlowTreeReq::HandleRequest() const {
832  Agent *agent = Agent::GetInstance();
833  std::vector<FlowMgmtManager *>::const_iterator it =
835  Inet4FlowTreeResponse *resp = new Inet4FlowTreeResponse();
836  std::vector<SandeshInetRouteFlowMgmtEntryLink> &resp_list =
837  const_cast<std::vector<SandeshInetRouteFlowMgmtEntryLink>&>
838  (resp->get_keys());
839  uint16_t mgr_idx = 0;
840  while (it != agent->pkt()->flow_mgmt_manager_iterator_end()) {
841  FlowMgmtManager *mgr = *it;
842  it++;
844  FlowMgmtTree::Tree &list = tree->tree();
845  FlowMgmtTree::Tree::iterator tree_it = list.begin();
846  while(tree_it != list.end()) {
847  InetRouteFlowMgmtKey *key = static_cast<InetRouteFlowMgmtKey *>
848  (tree_it->first);
849  string key_str = InetRouteFlowMgmtKeyToString(mgr_idx, key);
850  SandeshInetRouteFlowMgmtEntryLink entry;
851  entry.set_inet_route_flow_mgmt_key(key_str);
852  resp_list.push_back(entry);
853  ++tree_it;
854  }
855  ++mgr_idx;
856  }
857  resp->set_context(context());
858  resp->set_more(false);
859  resp->Response();
860 }
861 
862 void SNatPortConfigRequest::HandleRequest() const {
863  Agent *agent = Agent::GetInstance();
864  PortTableManager *pm =
865  agent->pkt()->get_flow_proto()->port_table_manager();
866 
867  SNatPortResponse *resp = new SNatPortResponse();
868  std::vector<PortConfigData> &config_list =
869  const_cast<std::vector<PortConfigData>&>(resp->get_port_config_list());
870 
871  for(uint16_t protocol = 0; protocol < IPPROTO_MAX; protocol++) {
872  const PortTable *pt = pm->GetPortTable(protocol);
873  if (pt == NULL) {
874  continue;
875  }
876 
877  const PortConfig *pc = pt->port_config();
878  //Only count specified
879  PortConfigData spc;
880  spc.port_count = pc->port_count;
881  spc.protocol = protocol;
882 
883  std::vector<PortConfig::PortRange>::const_iterator it =
884  pc->port_range.begin();
885  for(;it != pc->port_range.end(); it++) {
886  PortConfigRange pcr;
887  pcr.port_start = it->port_start;
888  pcr.port_end = it->port_end;
889  spc.port_range.push_back(pcr);
890  }
891 
892  spc.set_bound_port_list((pt->GetPortList()));
893  config_list.push_back(spc);
894  }
895  resp->set_context(context());
896  resp->set_more(false);
897  resp->Response();
898 }
899 
900 static void HandlePortFlowReq(uint16_t protocol, uint16_t port,
901  bool match_proto, bool match_port,
902  std::string context) {
903  Agent *agent = Agent::GetInstance();
904  PortTableManager *pm =
905  agent->pkt()->get_flow_proto()->port_table_manager();
906 
907  SNatPortFlowResponse *resp = new SNatPortFlowResponse();
908  std::vector<SNatPortFlow> &list =
909  const_cast<std::vector<SNatPortFlow>&>(resp->get_port_flow_list());
910 
911  uint16_t flow_count = 0;
912  uint16_t next_port = 0;
913  uint16_t proto = 0;
914  for(; proto < IPPROTO_MAX; proto++) {
915  const PortTable *pt = pm->GetPortTable(proto);
916  next_port = 0;
917  if (match_proto && proto != protocol) {
918  continue;
919  }
920 
921  if (proto < protocol) {
922  continue;
923  }
924 
925  if (pt == NULL) {
926  continue;
927  }
928 
929  std::vector<uint16_t> ports = pt->GetPortList();
930  std::vector<uint16_t>::const_iterator it = ports.begin();
931  for(; it != ports.end(); it++) {
932  if (match_port && port != *it) {
933  continue;
934  }
935 
936  if (match_port && port > *it) {
937  break;
938  }
939 
940  if (port > *it) {
941  continue;
942  }
943 
944  std::vector<FlowKey> flow_list;
945  pt->GetFlowKeyList(*it, flow_list);
946  flow_count += flow_list.size();
947 
948  SNatPortFlow snf;
949  snf.port = *it;
950  snf.protocol = proto;
951  std::vector<FlowKey>::iterator flow_it = flow_list.begin();
952  for (; flow_it != flow_list.end(); flow_it++) {
953  SNatFlowKey flow_key;
954  flow_key.nh = flow_it->nh;
955  flow_key.sip = flow_it->src_addr.to_string();
956  flow_key.dip = flow_it->dst_addr.to_string();
957  flow_key.src_port = flow_it->src_port;
958  flow_key.dst_port = flow_it->dst_port;
959  flow_key.protocol = flow_it->protocol;
960  snf.flows.push_back(flow_key);
961  }
962 
963  list.push_back(snf);
964 
965  if (flow_count >= 1) {
966  break;
967  }
968  }
969 
970  if (it != ports.end() && match_port == false) {
971  next_port = *it + 1;
972  }
973 
974  if (match_port == false) {
975  port = 0;
976  }
977 
978  if (flow_count >= 1) {
979  break;
980  }
981  }
982 
983  bool next = true;
984  if (match_proto && next_port == 0) {
985  next = false;
986  }
987 
988  if (proto == IPPROTO_MAX) {
989  next = false;
990  }
991 
992  if (next) {
993  std::stringstream str;
994  str << proto << ":" << next_port << ":" << match_proto
995  << ":" << match_port;
996  resp->set_flow_key(str.str());
997  }
998 
999  resp->set_context(context);
1000  resp->set_more(false);
1001  resp->Response();
1002 }
1003 
1004 void SNatPerPortFlowList::HandleRequest() const {
1005  bool match_proto = false;
1006  if (protocol != 0) {
1007  match_proto = true;
1008  }
1009 
1010  bool match_port = false;
1011  if (port != 0) {
1012  match_port = true;
1013  }
1014 
1015  HandlePortFlowReq(protocol, port, match_proto, match_port,
1016  context());
1017 }
1018 
1019 void NextPerPortFlowList::HandleRequest() const {
1020  using std::istringstream;
1021 
1022  uint16_t proto = 0;
1023  uint16_t port = 0;
1024  bool match_proto = false;
1025  bool match_port = false;
1026  std::string colon;
1027 
1028  std::stringstream ss(port_key);
1029  string item;
1030  const char ch = ':';
1031 
1032  size_t n = std::count(port_key.begin(), port_key.end(), ch);
1033  if (n != 3) {
1034  goto fail;
1035  }
1036 
1037  if (getline(ss, item, ch)) {
1038  istringstream(item) >> proto;
1039  }
1040  if (getline(ss, item, ch)) {
1041  istringstream(item) >> port;
1042  }
1043  if (getline(ss, item, ch)) {
1044  istringstream(item) >> match_proto;
1045  }
1046  if (getline(ss, item, ch)) {
1047  istringstream(item) >> match_port;
1048  }
1049 
1050  HandlePortFlowReq(proto, port, match_proto, match_port,
1051  context());
1052 
1053 fail:
1054  FlowErrorResp *resp = new FlowErrorResp();
1055  resp->set_context(context());
1056  resp->set_more(false);
1057  resp->Response();
1058 }
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
void SendResponse(SandeshResponse *resp)
IpAddress src_addr
Definition: flow_entry.h:213
FlowRecordsResp * resp_obj_
FlowEntryMap flow_entry_map_
Definition: flow_table.h:297
MatchAclParamsList m_reverse_acl_l
Definition: flow_entry.h:236
void DeleteAll()
Definition: flow_table.cc:429
static Agent * GetInstance()
Definition: agent.h:436
#define SET_SANDESH_FLOW_DATA(agent, data, fe, info)
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
std::vector< FlowMgmtManager * >::const_iterator flow_mgmt_manager_iterator_end() const
Definition: pkt_init.h:53
static InetRouteFlowMgmtKey * StringToInetRouteFlowMgmtKey(const string &key, uint16_t *id)
FlowStatsManager * flow_stats_manager() const
Definition: agent.cc:925
static std::string GetFlowKey(const FlowKey &key, uint16_t partition_id)
static const char kDelimiter
static void HandlePortFlowReq(uint16_t protocol, uint16_t port, bool match_proto, bool match_port, std::string context)
bool SetFlowKey(std::string key)
MatchAclParamsList m_vrf_assign_acl_l
Definition: flow_entry.h:274
IpAddress dst_addr
Definition: flow_entry.h:214
FlowMgmtEntry * Find(FlowMgmtKey *key)
uint32_t flow_table_count() const
Definition: flow_proto.h:68
uint32_t vrf_assign_acl_action
Definition: flow_entry.h:275
MatchAclParamsList m_acl_l
Definition: flow_entry.h:258
boost::asio::ip::address IpAddress
Definition: address.h:13
uint16_t port_count
AgentStats * stats() const
Definition: agent.cc:881
FlowTable * flow_table(uint16_t index) const
Definition: pkt_init.cc:97
uint64_t flow_created() const
Definition: agent_stats.h:100
SessionPolicy aps_policy
Definition: flow_entry.h:265
Definition: task_int.h:10
uint32_t action
Definition: acl.h:44
uint16_t table_index() const
Definition: flow_table.h:198
static void SetOneAclInfo(FlowAclInfo *policy, uint32_t action, const MatchAclParamsList &acl_list)
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
uint32_t out_action
Definition: flow_entry.h:234
PortTableManager * port_table_manager()
Definition: flow_proto.h:126
void SetActionStr(const FlowAction &action_info, std::vector< ActionStr > &action_str_l)
Definition: flow_entry.cc:3015
uint8_t protocol
Definition: flow_entry.h:215
void set_delete_op(bool delete_op)
static const std::string start_key
uint32_t total_alloc() const
Definition: flow_table.h:112
uint32_t out_mirror_action
Definition: flow_entry.h:272
const std::string & sg_rule_uuid() const
Definition: flow_entry.h:633
uint32_t Size() const
InetRouteFlowMgmtTree * ip4_route_flow_mgmt_tree()
Definition: flow_mgmt.h:325
uint32_t action
Definition: flow_entry.h:230
uint64_t flow_aged() const
Definition: agent_stats.h:107
MatchAclParamsList m_out_mirror_acl_l
Definition: flow_entry.h:271
const FlowKey & key() const
Definition: flow_entry.h:594
std::string resp_data_
FlowTable * GetTable(uint16_t index) const
Definition: flow_proto.cc:261
virtual void Response()
Definition: p/sandesh.h:502
void UpdateAgeTimeInSeconds(uint32_t age_time)
Tree & tree()
uint32_t policy_action
Definition: flow_entry.h:259
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
Definition: agent.h:358
boost::intrusive::list< FlowMgmtKeyNode, Node > FlowList
static TaskScheduler * GetInstance()
Definition: task.cc:547
void Enqueue(Task *task)
Enqueues a task for running. Starts task if all policy rules are met else puts task in waitq...
Definition: task.cc:636
SessionPolicy fwaas_policy
Definition: flow_entry.h:266
MatchAclParamsList m_acl_l
Definition: flow_entry.h:228
MatchAclParamsList m_reverse_out_acl_l
Definition: flow_entry.h:240
uint32_t free_count() const
Definition: flow_table.h:110
static boost::posix_time::ptime UTCUsecToPTime(uint64_t tusec)
Definition: time_util.h:38
uint32_t out_policy_action
Definition: flow_entry.h:262
static const std::string & NullString()
Definition: agent.h:437
static const int kMaxFlowResponse
PktSandeshFlowStats(Agent *agent, FlowStatsCollectorRecordsResp *obj, std::string resp_ctx, std::string key)
uint64_t max_flow_count() const
Definition: agent_stats.h:102
const LinkLocalFlowInfoMap & linklocal_flow_info_map()
Definition: flow_table.h:207
const PortConfig * port_config() const
Definition: flow_entry.h:1050
std::map< int, LinkLocalFlowInfo > LinkLocalFlowInfoMap
Definition: flow_table.h:170
uint32_t vrf_id() const
const FlowList & flow_list() const
uint16_t partition_id_
const PortTable * GetPortTable(uint8_t proto)
Definition: flow_entry.h:1115
FlowProto * get_flow_proto() const
Definition: pkt_init.h:43
IpAddress ip() const
uint16_t src_port
Definition: flow_entry.h:216
static string InetRouteFlowMgmtKeyToString(uint16_t id, InetRouteFlowMgmtKey *key)
std::vector< FlowMgmtManager * >::const_iterator flow_mgmt_manager_iterator_begin() const
Definition: pkt_init.h:49
uint8_t plen() const
static void SetAclInfo(SandeshFlowData &data, FlowEntry *fe)
size_t Size()
Definition: flow_table.h:199
MatchAclParamsList m_mirror_acl_l
Definition: flow_entry.h:268
Address::Family family
Definition: flow_entry.h:211
uint32_t FlowCount() const
Definition: flow_proto.cc:265
MatchAclParamsList m_out_acl_l
Definition: flow_entry.h:261
MatchAclParamsList m_out_acl_l
Definition: flow_entry.h:232
uint16_t dst_port
Definition: flow_entry.h:217
void set_context(std::string context)
Definition: p/sandesh.h:310
bool SetProto(std::string &key)
uint32_t total_free() const
Definition: flow_table.h:113
std::list< MatchAclParams > MatchAclParamsList
Definition: flow_entry.h:220
std::vector< uint16_t > GetPortList() const
Definition: flow_entry.h:1054
uint32_t reverse_action
Definition: flow_entry.h:238
FlowStatsCollectorRecordsResp * resp_
FlowKey flow_iteration_key_
uint32_t action_summary
Definition: flow_entry.h:246
const std::string & nw_ace_uuid() const
Definition: flow_entry.h:636
FlowMgmtManagerList flow_mgmt_manager_list() const
Definition: pkt_init.h:36
Definition: acl.h:35
PktModule * pkt() const
Definition: agent.cc:965
uint32_t nh
Definition: flow_entry.h:212
uint32_t reverse_out_action
Definition: flow_entry.h:242
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
PktSandeshFlow(Agent *agent, FlowRecordsResp *obj, std::string resp_ctx, std::string key)
SessionPolicy sg_policy
Definition: flow_entry.h:264
FlowEntry * flow_entry() const
uint16_t flow_thread_count() const
Definition: agent.h:1202
void SetSandeshFlowData(std::vector< SandeshFlowData > &list, FlowEntry *fe, const FlowExportInfo *info)
std::map< FlowMgmtKey *, FlowMgmtEntry *, FlowMgmtKeyCmp > Tree
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
const MatchPolicy & match_p() const
Definition: flow_entry.h:670
std::vector< PortRange > port_range
const FlowStatsCollectorObject * Find(uint32_t proto, uint32_t port) const
virtual void set_more(const bool val)=0
FlowEntryFreeList * free_list()
Definition: flow_table.h:239
bool FindFlowExportInfo(const FlowEntry *fe, FlowEntryTree::iterator &it)
virtual ~PktSandeshFlow()
void GetFlowKeyList(uint16_t port, std::vector< FlowKey > &key) const
Definition: flow_entry.cc:4109
uint32_t GetAgeTimeInSeconds() const
FlowStatsCollector * fsc() const
Definition: flow_entry.h:728
FlowStatsCollectorObject * default_flow_stats_collector_obj()
uint32_t mirror_action
Definition: flow_entry.h:269