LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - pkt_sandesh_flow.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 661 0.0 %
Date: 2026-11-09 02:10:49 Functions: 0 30 0.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14