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