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

Generated by: LCOV version 1.14