LCOV - code coverage report
Current view: top level - vnsw/agent/pkt - flow_entry.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 140 196 71.4 %
Date: 2026-11-09 02:10:49 Functions: 70 94 74.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef __AGENT_PKT_FLOW_ENTRY_H__
       7             : #define __AGENT_PKT_FLOW_ENTRY_H__
       8             : 
       9             : #include <mutex>
      10             : #include <atomic>
      11             : 
      12             : #include <boost/uuid/uuid_io.hpp>
      13             : #include <boost/intrusive_ptr.hpp>
      14             : #include <boost/intrusive/list.hpp>
      15             : #include <base/util.h>
      16             : #include <base/address.h>
      17             : #include <db/db_table_walker.h>
      18             : #include <cmn/agent_cmn.h>
      19             : #include <oper/mirror_table.h>
      20             : #include <filter/traffic_action.h>
      21             : #include <filter/acl_entry.h>
      22             : #include <filter/acl.h>
      23             : #include <pkt/pkt_types.h>
      24             : #include <pkt/pkt_handler.h>
      25             : #include <pkt/pkt_init.h>
      26             : #include <pkt/pkt_flow_info.h>
      27             : #include <pkt/flow_token.h>
      28             : #include <sandesh/sandesh_trace.h>
      29             : #include <oper/global_vrouter.h>
      30             : #include <oper/vn.h>
      31             : #include <oper/vm.h>
      32             : #include <oper/interface_common.h>
      33             : #include <oper/nexthop.h>
      34             : #include <oper/route_common.h>
      35             : #include <oper/sg.h>
      36             : #include <oper/vrf.h>
      37             : #include <filter/acl.h>
      38             : #include <sandesh/common/flow_types.h>
      39             : 
      40             : class FlowTableKSyncEntry;
      41             : class FlowEntry;
      42             : class FlowExportInfo;
      43             : class FlowStatsCollector;
      44             : class Token;
      45             : class FlowMgmtRequest;
      46             : class FlowEntryInfo;
      47             : struct FlowUveFwPolicyInfo;
      48             : struct FlowUveVnAcePolicyInfo;
      49             : typedef std::unique_ptr<FlowEntryInfo> FlowMgmtEntryInfoPtr;
      50             : 
      51             : ////////////////////////////////////////////////////////////////////////////
      52             : // This is helper struct to carry parameters of reverse-flow. When flow is
      53             : // being deleted, the relationship between forward and reverse flows are
      54             : // broken. However, some info of reverse flow is needed during export of flows
      55             : // for FlowStatsCollector. This information of reverse flow is carried in the
      56             : // following struct.
      57             : ////////////////////////////////////////////////////////////////////////////
      58             : struct RevFlowDepParams {
      59             :     boost::uuids::uuid rev_uuid_;
      60             :     boost::uuids::uuid rev_egress_uuid_;
      61             :     IpAddress sip_;
      62             :     std::string vmi_uuid_;
      63             :     std::string sg_uuid_;
      64             :     std::string vm_cfg_name_;
      65             :     uint16_t drop_reason_;
      66             :     std::string nw_ace_uuid_;
      67             :     FlowAction action_info_;
      68             : 
      69       10163 :     RevFlowDepParams() : rev_uuid_(), rev_egress_uuid_(), sip_(), vmi_uuid_(),
      70       10163 :                          sg_uuid_(), vm_cfg_name_(), drop_reason_(),
      71       10163 :                          nw_ace_uuid_(), action_info_() {
      72       10163 :     }
      73             : 
      74             :     RevFlowDepParams(const boost::uuids::uuid &rev_uuid,
      75             :                      const boost::uuids::uuid &rev_egress_uuid,
      76             :                      IpAddress sip,
      77             :                      const std::string &vmi_uuid,
      78             :                      const std::string &sg_uuid,
      79             :                      const std::string &vm_cfg_name,
      80             :                      uint16_t &drop_reason,
      81             :                      std::string &nw_ace_uuid,
      82             :                      FlowAction &action_info) : rev_uuid_(rev_uuid),
      83             :         rev_egress_uuid_(rev_egress_uuid), sip_(sip), vmi_uuid_(vmi_uuid),
      84             :         sg_uuid_(sg_uuid), vm_cfg_name_(vm_cfg_name),
      85             :         drop_reason_(drop_reason), nw_ace_uuid_(nw_ace_uuid),
      86             :         action_info_(action_info) {
      87             :     }
      88             : };
      89             : 
      90             : ////////////////////////////////////////////////////////////////////////////
      91             : // Helper class to manage following,
      92             : // 1. VM referred by the flow
      93             : // 2. Per VM flow counters to apply per-vm flow limits
      94             : //    - Number of flows for a VM
      95             : //    - Number of linklocal flows for a VM
      96             : // 3. socket opened for linklocal flows
      97             : ////////////////////////////////////////////////////////////////////////////
      98             : class VmFlowRef {
      99             : public:
     100             :     static const int kInvalidFd=-1;
     101             :     VmFlowRef();
     102             :     VmFlowRef(const VmFlowRef &rhs);
     103             :     ~VmFlowRef();
     104             : 
     105             :     void Init(FlowEntry *flow);
     106             :     void operator=(const VmFlowRef &rhs);
     107             :     void Reset(bool reset_flow);
     108             :     void FreeRef();
     109             :     void FreeFd();
     110             :     void SetVm(const VmEntry *vm);
     111             :     bool AllocateFd(Agent *agent, uint8_t l3_proto);
     112             :     void Move(VmFlowRef *rhs);
     113             : 
     114         112 :     int fd() const { return fd_; }
     115           0 :     uint16_t port() const { return port_; }
     116             :     const VmEntry *vm() const { return vm_.get(); }
     117             : private:
     118             :     // IMPORTANT: Keep this structure assignable. Assignment operator is used in
     119             :     // FlowEntry::Copy() on this structure
     120             :     VmEntryConstRef vm_;
     121             :     int fd_;
     122             :     uint16_t port_;
     123             :     FlowEntry *flow_;
     124             : };
     125             : 
     126             : typedef boost::intrusive_ptr<FlowEntry> FlowEntryPtr;
     127             : 
     128             : struct FlowKey {
     129       15793 :     FlowKey() :
     130       15793 :         family(Address::UNSPEC), nh(0), src_addr(Ip4Address(0)),
     131       15794 :         dst_addr(Ip4Address(0)), protocol(0),
     132       15794 :         src_port(0), dst_port(0){
     133       15794 :     }
     134             : 
     135         222 :     FlowKey(uint32_t nh_p, const Ip4Address &sip_p, const Ip4Address &dip_p,
     136             :             uint8_t proto_p, uint16_t sport_p, uint16_t dport_p)
     137         222 :         : family(Address::INET), nh(nh_p), src_addr(sip_p), dst_addr(dip_p),
     138         222 :         protocol(proto_p), src_port(sport_p), dst_port(dport_p) {
     139         222 :     }
     140             : 
     141         224 :     FlowKey(uint32_t nh_p, const IpAddress &sip_p, const IpAddress &dip_p,
     142             :             uint8_t proto_p, uint16_t sport_p, uint16_t dport_p)
     143         224 :         : family(sip_p.is_v4() ? Address::INET : Address::INET6), nh(nh_p),
     144         224 :         src_addr(sip_p), dst_addr(dip_p), protocol(proto_p), src_port(sport_p),
     145         224 :         dst_port(dport_p) {
     146         224 :     }
     147             : 
     148         304 :     FlowKey(const FlowKey &key) :
     149         304 :         family(key.family), nh(key.nh), src_addr(key.src_addr),
     150         304 :         dst_addr(key.dst_addr), protocol(key.protocol), src_port(key.src_port),
     151         304 :         dst_port(key.dst_port) {
     152         304 :     }
     153             : 
     154             :     // Comparator for the flow-entry
     155        6542 :     bool IsLess(const FlowKey &key) const {
     156        6542 :         if (family != key.family)
     157           0 :             return family < key.family;
     158             : 
     159        6542 :         if (nh != key.nh)
     160        5102 :             return nh < key.nh;
     161             : 
     162        1440 :         if (src_addr != key.src_addr)
     163         322 :             return src_addr < key.src_addr;
     164             : 
     165        1118 :         if (dst_addr != key.dst_addr)
     166          26 :             return dst_addr < key.dst_addr;
     167             : 
     168        1092 :         if (protocol != key.protocol)
     169           0 :             return protocol < key.protocol;
     170             : 
     171        1092 :         if (src_port != key.src_port)
     172         254 :             return src_port < key.src_port;
     173             : 
     174         838 :         return dst_port < key.dst_port;
     175             :     }
     176             : 
     177           3 :     bool IsEqual(const FlowKey &key) const {
     178           3 :         if (family != key.family)
     179           0 :             return false;
     180             : 
     181           3 :         if (nh != key.nh)
     182           0 :             return false;
     183             : 
     184           3 :         if (src_addr != key.src_addr)
     185           0 :             return false;
     186             : 
     187           3 :         if (dst_addr != key.dst_addr)
     188           0 :             return false;
     189             : 
     190           3 :         if (protocol != key.protocol)
     191           0 :             return false;
     192             : 
     193           3 :         if (src_port != key.src_port)
     194           0 :             return false;
     195             : 
     196           3 :         if (dst_port != key.dst_port)
     197           0 :             return false;
     198             : 
     199           3 :         return true;
     200             :     }
     201             : 
     202             :     void Reset() {
     203             :         family = Address::UNSPEC;
     204             :         nh = -1;
     205             :         src_addr = Ip4Address(0);
     206             :         dst_addr = Ip4Address(0);
     207             :         protocol = -1;
     208             :         src_port = -1;
     209             :         dst_port = -1;
     210             :     }
     211             : 
     212             :     Address::Family family;
     213             :     uint32_t nh;
     214             :     IpAddress src_addr;
     215             :     IpAddress dst_addr;
     216             :     uint8_t protocol;
     217             :     uint16_t src_port;
     218             :     uint16_t dst_port;
     219             : };
     220             : 
     221             : typedef std::list<MatchAclParams> MatchAclParamsList;
     222             : 
     223             : struct SessionPolicy {
     224             :     void Reset();
     225             :     void ResetAction();
     226             :     void ResetPolicy();
     227             :     void ResetRuleMatchInfo();
     228             : 
     229             :     MatchAclParamsList m_acl_l;
     230             :     bool rule_present;
     231             :     uint32_t action;
     232             : 
     233             :     MatchAclParamsList m_out_acl_l;
     234             :     bool out_rule_present;
     235             :     uint32_t out_action;
     236             : 
     237             :     MatchAclParamsList m_reverse_acl_l;
     238             :     bool reverse_rule_present;
     239             :     uint32_t reverse_action;
     240             : 
     241             :     MatchAclParamsList m_reverse_out_acl_l;
     242             :     bool reverse_out_rule_present;
     243             :     uint32_t reverse_out_action;
     244             : 
     245             :     std::string rule_uuid_;
     246             :     std::string acl_name_;
     247             :     uint32_t action_summary;
     248             : };
     249             : 
     250             : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
     251             : // FlowEntry::Copy() on this structure
     252             : struct MatchPolicy {
     253             :     MatchPolicy();
     254             :     ~MatchPolicy();
     255             : 
     256             :     void Reset();
     257             : 
     258             :     // IMPORTANT: Keep this structure assignable.
     259             :     MatchAclParamsList m_acl_l;
     260             :     uint32_t policy_action;
     261             : 
     262             :     MatchAclParamsList m_out_acl_l;
     263             :     uint32_t out_policy_action;
     264             : 
     265             :     SessionPolicy sg_policy;
     266             :     SessionPolicy aps_policy;
     267             :     SessionPolicy fwaas_policy;
     268             : 
     269             :     MatchAclParamsList m_mirror_acl_l;
     270             :     uint32_t mirror_action;
     271             : 
     272             :     MatchAclParamsList m_out_mirror_acl_l;
     273             :     uint32_t out_mirror_action;
     274             : 
     275             :     MatchAclParamsList m_vrf_assign_acl_l;
     276             :     uint32_t vrf_assign_acl_action;
     277             : 
     278             :     FlowAction action_info;
     279             : };
     280             : 
     281             : // IMPORTANT: Keep this structure assignable. Assignment operator is used in
     282             : // FlowEntry::Copy() on this structure
     283             : struct FlowData {
     284             :     FlowData();
     285             :     ~FlowData();
     286             : 
     287             :     void Reset();
     288             :     std::vector<std::string> SourceVnList() const;
     289             :     std::vector<std::string> DestinationVnList() const;
     290             :     std::vector<std::string> OriginVnSrcList() const;
     291             :     std::vector<std::string> OriginVnDstList() const;
     292             : 
     293             :     MacAddress smac;
     294             :     MacAddress dmac;
     295             :     std::string source_vn_match;
     296             :     std::string dest_vn_match;
     297             :     std::string origin_vn_src;
     298             :     std::string origin_vn_dst;
     299             :     VnListType source_vn_list;
     300             :     VnListType dest_vn_list;
     301             :     VnListType origin_vn_src_list;
     302             :     VnListType origin_vn_dst_list;
     303             :     SecurityGroupList source_sg_id_l;
     304             :     SecurityGroupList dest_sg_id_l;
     305             :     TagList source_tag_id_l;
     306             :     TagList dest_tag_id_l;
     307             :     uint32_t flow_source_vrf;
     308             :     uint32_t flow_dest_vrf;
     309             : 
     310             :     MatchPolicy match_p;
     311             :     VnEntryConstRef vn_entry;
     312             :     InterfaceConstRef intf_entry;
     313             :     VmFlowRef  in_vm_entry;
     314             :     VmFlowRef  out_vm_entry;
     315             :     NextHopConstRef src_ip_nh;
     316             :     uint32_t vrf;
     317             :     uint32_t mirror_vrf;
     318             :     uint32_t dest_vrf;
     319             :     uint32_t component_nh_idx;
     320             :     uint32_t bgp_as_a_service_sport;
     321             :     uint32_t bgp_as_a_service_dport;
     322             :     boost::uuids::uuid bgp_health_check_uuid;
     323             :     uint32_t ttl;
     324             :     // In case of policy on fabric, the forwarding happens in
     325             :     // agent_->fabric_vrf(), but policy processing must happen in
     326             :     // agent_->fabric_policy_vrf(). Storing the route infor for
     327             :     // fabric_policy_vrf() for tracking purpose
     328             :     uint32_t src_policy_vrf;
     329             :     uint32_t src_policy_plen;
     330             :     uint32_t dst_policy_vrf;
     331             :     uint32_t dst_policy_plen;
     332             : 
     333             :     // Stats
     334             :     uint8_t source_plen;
     335             :     uint8_t dest_plen;
     336             :     uint16_t drop_reason;
     337             :     bool vrf_assign_evaluated;
     338             :     uint32_t            if_index_info;
     339             :     TunnelInfo          tunnel_info;
     340             :     // map for references to the routes which were ignored due to more specific
     341             :     // route this will be used to trigger flow re-compute to use more specific
     342             :     // on route add. key for the map is vrf and data is prefix length
     343             :     FlowRouteRefMap     flow_source_plen_map;
     344             :     FlowRouteRefMap     flow_dest_plen_map;
     345             : 
     346             :     // RPF related
     347             :     bool enable_rpf;
     348             :     // RPF NH for the flow
     349             :     NextHopConstRef rpf_nh;
     350             :     // When RPF is derived from a INET route, flow-management uses VRF and plen
     351             :     // below to track the route for any NH change
     352             :     // rpf_vrf will be VrfEntry::kInvalidIndex if flow uses l2-route for RPF
     353             :     uint32_t rpf_vrf;
     354             :     uint8_t rpf_plen;
     355             : 
     356             :     bool disable_validation; // ignore RPF on specific flows (like BFD health check)
     357             : 
     358             :     std::string vm_cfg_name;
     359             :     uint32_t acl_assigned_vrf_index_;
     360             :     uint32_t qos_config_idx;
     361             :     uint16_t allocated_port_;
     362             :     uint8_t underlay_gw_index_;
     363             :     // IMPORTANT: Keep this structure assignable. Assignment operator is used in
     364             :     // FlowEntry::Copy() on this structure
     365             : };
     366             : 
     367             : struct FlowEventLog {
     368             :     enum Event {
     369             :         FLOW_ADD,
     370             :         FLOW_UPDATE,
     371             :         FLOW_DELETE,
     372             :         FLOW_EVICT,
     373             :         FLOW_HANDLE_ASSIGN,
     374             :         FLOW_MSG_SKIP_EVICTED,
     375             :         EVENT_MAXIMUM
     376             :     };
     377             : 
     378             :     FlowEventLog();
     379             :     ~FlowEventLog();
     380             : 
     381             :     uint64_t time_;
     382             :     Event event_;
     383             :     uint32_t flow_handle_;
     384             :     uint8_t flow_gen_id_;
     385             :     FlowTableKSyncEntry *ksync_entry_;
     386             :     uint32_t hash_id_;
     387             :     uint8_t gen_id_;
     388             :     uint32_t vrouter_flow_handle_;
     389             :     uint8_t vrouter_gen_id_;
     390             : };
     391             : 
     392             : // There are 4 actions supported,
     393             : // Flow recomputation goes thru 2 stages of processing,
     394             : //
     395             : // - recompute_dbentry_ : In this stage, flow is enqueued to flow-update-queue
     396             : //                        as a result of db-entry add/delete/change.
     397             : // - recompute_         : In this stage, flow is enqueued to flow-event-queue
     398             : //                        for recomputation of flow
     399             : // - delete_            : Specifies that delete action is pending on flow.
     400             : // - recompute_         : Specifies that flow is enqueued into flow-event-queue
     401             : //                        for recomputation.
     402             : //
     403             : // The actions have a priority, the higher priorty action overrides lower
     404             : // priority actions. The priority in decreasing order is,
     405             : // - delete_
     406             : // - recompute_
     407             : // - recompute_dbentry_
     408             : // - revaluate_
     409             : //
     410             : // The flags are also used for state-compression of objects. The state
     411             : // compression is acheived with,
     412             : //
     413             : // - Before Event Enqueue :
     414             : //   Before enqueuing an event, the FlowEvent module checks if the
     415             : //   corresponding action or higher priority action is pending. If so, the
     416             : //   event is ignored.
     417             : //   Note, if the lower priority event is pending, the higher priority event
     418             : //   is still enqueued. The lower priority event is ignored later as given below
     419             : //
     420             : // - On Event dequeue :
     421             : //   After dequeuing an event, FlowEvent module checks if a higher priority
     422             : //   event is pending. If so, the current event is ignored.
     423             : //
     424             : // - Post Event processing:
     425             : //   Once the event is processed, the corresponding action is cleared for both
     426             : //   forward and reverse flows. Clearing an action also clears lower priority
     427             : //   actions
     428             : class FlowPendingAction {
     429             : public:
     430             :     FlowPendingAction();
     431             :     ~FlowPendingAction();
     432             : 
     433             :     void Reset();
     434             : 
     435             :     bool CanDelete();
     436             :     bool SetDelete();
     437             :     void ResetDelete();
     438             : 
     439             :     bool CanRecompute();
     440             :     bool SetRecompute();
     441             :     void ResetRecompute();
     442             : 
     443             :     bool CanRecomputeDBEntry();
     444             :     bool SetRecomputeDBEntry();
     445             :     void ResetRecomputeDBEntry();
     446             : 
     447             :     bool CanRevaluate();
     448             :     bool SetRevaluate();
     449             :     void ResetRevaluate();
     450             : private:
     451             :     // delete pending
     452             :     bool delete_;
     453             :     // Flow pending complete recompute
     454             :     bool recompute_;
     455             :     // Flow pending recompute-dbentry
     456             :     bool recompute_dbentry_;
     457             :     // Flow pending revaluation due to change in interface, vn, acl and nh
     458             :     bool revaluate_;
     459             : };
     460             : 
     461             : class FlowEntry {
     462             :     public:
     463             :     enum FlowShortReason {
     464             :         /* Please update FlowEntry::FlowDropReasonStr whenever entries are added
     465             :          * to the below enum */
     466             :         SHORT_UNKNOWN = 0,
     467             :         SHORT_UNAVIALABLE_INTERFACE,
     468             :         SHORT_IPV4_FWD_DIS,
     469             :         SHORT_UNAVIALABLE_VRF,
     470             :         SHORT_NO_SRC_ROUTE,
     471             :         SHORT_NO_DST_ROUTE,
     472             :         SHORT_AUDIT_ENTRY,
     473             :         SHORT_VRF_CHANGE,
     474             :         SHORT_NO_REVERSE_FLOW,
     475             :         SHORT_REVERSE_FLOW_CHANGE,
     476             :         SHORT_NAT_CHANGE,
     477             :         SHORT_FLOW_LIMIT,
     478             :         SHORT_LINKLOCAL_SRC_NAT,
     479             :         SHORT_FAILED_VROUTER_INSTALL,
     480             :         SHORT_INVALID_L2_FLOW,
     481             :         SHORT_FLOW_ON_TSN,
     482             :         SHORT_NO_MIRROR_ENTRY,
     483             :         SHORT_SAME_FLOW_RFLOW_KEY,
     484             :         SHORT_PORT_MAP_DROP,
     485             :         SHORT_NO_SRC_ROUTE_L2RPF,
     486             :         SHORT_FAT_FLOW_NAT_CONFLICT,
     487             :         SHORT_L3MH_PHY_INTF_DOWN,
     488             :         SHORT_MAX
     489             :     };
     490             : 
     491             :     enum FlowDropReason {
     492             :         /* Please update FlowEntry::FlowDropReasonStr whenever entries are added
     493             :          * to the below enum */
     494             :         DROP_UNKNOWN = 0,
     495             :         DROP_POLICY = SHORT_MAX,
     496             :         DROP_OUT_POLICY,
     497             :         DROP_SG,
     498             :         DROP_OUT_SG,
     499             :         DROP_REVERSE_SG,
     500             :         DROP_REVERSE_OUT_SG,
     501             :         DROP_FIREWALL_POLICY,
     502             :         DROP_OUT_FIREWALL_POLICY,
     503             :         DROP_REVERSE_FIREWALL_POLICY,
     504             :         DROP_REVERSE_OUT_FIREWALL_POLICY,
     505             :         DROP_FWAAS_POLICY,
     506             :         DROP_FWAAS_OUT_POLICY,
     507             :         DROP_FWAAS_REVERSE_POLICY,
     508             :         DROP_FWAAS_REVERSE_OUT_POLICY,
     509             :     };
     510             : 
     511             :     enum FlowPolicyState {
     512             :         NOT_EVALUATED,
     513             :         IMPLICIT_ALLOW, /* Due to No Acl rules */
     514             :         IMPLICIT_DENY,
     515             :         DEFAULT_GW_ICMP_OR_DNS, /* DNS/ICMP pkt to/from default gateway */
     516             :         LINKLOCAL_FLOW, /* No policy applied for linklocal flow */
     517             :         MULTICAST_FLOW, /* No policy applied for multicast flow */
     518             :         BGPROUTERSERVICE_FLOW, /* No policy applied for bgp router service flow */
     519             :         NON_IP_FLOW,    /* Flow due to bridging */
     520             :     };
     521             : 
     522             :     static const uint32_t kInvalidFlowHandle=0xFFFFFFFF;
     523             :     static const uint8_t kMaxMirrorsPerFlow=0x2;
     524             :     static const std::map<FlowPolicyState, const char*> FlowPolicyStateStr;
     525             :     static const std::map<uint16_t, const char*> FlowDropReasonStr;
     526             :     static const uint32_t kFlowRetryAttempts = 5;
     527             :     // Don't go beyond PCAP_END, pcap type is one byte
     528             :     enum PcapType {
     529             :         PCAP_CAPTURE_HOST = 1,
     530             :         PCAP_FLAGS = 2,
     531             :         PCAP_SOURCE_VN = 3,
     532             :         PCAP_DEST_VN = 4,
     533             :         PCAP_TLV_END = 255
     534             :     };
     535             : 
     536             :     enum FlowEntryFlags {
     537             :         NatFlow         = 1 << 0,
     538             :         LocalFlow       = 1 << 1,
     539             :         ShortFlow       = 1 << 2,
     540             :         LinkLocalFlow   = 1 << 3,
     541             :         ReverseFlow     = 1 << 4,
     542             :         EcmpFlow        = 1 << 5,
     543             :         IngressDir      = 1 << 6,
     544             :         Trap            = 1 << 7,
     545             :         Multicast       = 1 << 8,
     546             :         // a local port bind is done (used as as src port for linklocal nat)
     547             :         LinkLocalBindLocalSrcPort = 1 << 9,
     548             :         TcpAckFlow                = 1 << 10,
     549             :         UnknownUnicastFlood       = 1 << 11,
     550             :         BgpRouterService          = 1 << 12,
     551             :         AliasIpFlow               = 1 << 13,
     552             :         FabricControlFlow         = 1 << 14,
     553             :         FabricFlow                = 1 << 15,
     554             :         HbfFlow                   = 1 << 16
     555             :     };
     556             : 
     557             :     enum HbsInterface {
     558             :         HBS_INTERFACE_INVALID  = 0,
     559             :         HBS_INTERFACE_LEFT     = 1,
     560             :         HBS_INTERFACE_RIGHT    = 2
     561             :     };
     562             : 
     563             :     FlowEntry(FlowTable *flow_table);
     564             :     virtual ~FlowEntry();
     565             : 
     566             :     void Reset(const FlowKey &k);
     567             :     void Reset();
     568             : 
     569             :     // Copy data fields from rhs
     570             :     void Copy(FlowEntry *rhs, bool update);
     571             : 
     572             :     void InitFwdFlow(const PktFlowInfo *info, const PktInfo *pkt,
     573             :                      const PktControlInfo *ctrl,
     574             :                      const PktControlInfo *rev_ctrl, FlowEntry *rflow,
     575             :                      Agent *agent);
     576             :     void InitRevFlow(const PktFlowInfo *info, const PktInfo *pkt,
     577             :                      const PktControlInfo *ctrl,
     578             :                      const PktControlInfo *rev_ctrl, FlowEntry *rflow,
     579             :                      Agent *agent);
     580             :     void InitAuditFlow(uint32_t flow_idx, uint8_t gen_id);
     581             :     static void Init();
     582             : 
     583             :     static AgentRoute *GetL2Route(const VrfEntry *entry, const MacAddress &mac);
     584             :     static AgentRoute *GetUcRoute(const VrfEntry *entry, const IpAddress &addr);
     585             :     static AgentRoute *GetEvpnRoute(const VrfEntry *entry, const MacAddress &mac,
     586             :                                     const IpAddress &addr, uint32_t ethernet_tag);
     587          32 :     static const SecurityGroupList &default_sg_list() {
     588          32 :         return default_sg_list_;
     589             :     }
     590             :     static FlowEntry *Allocate(const FlowKey &key, FlowTable *flow_table);
     591             :     static bool ShouldDrop(uint32_t action);
     592             : 
     593             :     // Flow accessor routines
     594           0 :     int GetRefCount() { return refcount_; }
     595        7779 :     const FlowKey &key() const { return key_;}
     596       12603 :     FlowData &data() { return data_;}
     597         209 :     const FlowData &data() const { return data_;}
     598       10872 :     FlowTable *flow_table() const { return flow_table_; }
     599        2640 :     bool l3_flow() const { return l3_flow_; }
     600        2511 :     uint8_t gen_id() const { return gen_id_; }
     601        4892 :     uint32_t flow_handle() const { return flow_handle_; }
     602             :     void set_flow_handle(uint32_t flow_handle, uint8_t gen_id);
     603        6415 :     FlowEntry *reverse_flow_entry() { return reverse_flow_entry_.get(); }
     604             :     uint32_t flags() const { return flags_; }
     605         197 :     const FlowEntry *reverse_flow_entry() const {
     606         197 :         return reverse_flow_entry_.get();
     607             :     }
     608         743 :     void set_reverse_flow_entry(FlowEntry *reverse_flow_entry) {
     609         743 :         reverse_flow_entry_ = reverse_flow_entry;
     610         743 :     }
     611       41335 :     bool is_flags_set(const FlowEntryFlags &flags) const {
     612       41335 :         return (flags_ & flags);
     613             :     }
     614         556 :     void set_flags(const FlowEntryFlags &flags) { flags_ |= flags; }
     615        3132 :     void reset_flags(const FlowEntryFlags &flags) { flags_ &= ~flags; }
     616             :     void set_source_sg_id_l(const SecurityGroupList &sg_l) {
     617             :         data_.source_sg_id_l = sg_l;
     618             :     }
     619             :     void set_dest_sg_id_l(const SecurityGroupList &sg_l) {
     620             :         data_.dest_sg_id_l = sg_l;
     621             :     }
     622          59 :     int linklocal_src_port() const { return data_.in_vm_entry.port(); }
     623             :     int linklocal_src_port_fd() const { return data_.in_vm_entry.fd(); }
     624             :     const std::string& acl_assigned_vrf() const;
     625             :     void set_acl_assigned_vrf_index();
     626             :     uint32_t acl_assigned_vrf_index() const;
     627          88 :     uint32_t fip() const { return fip_; }
     628          44 :     VmInterfaceKey fip_vmi() const { return fip_vmi_; }
     629             :     uint32_t reverse_flow_fip() const;
     630             :     VmInterfaceKey reverse_flow_vmi() const;
     631             :     void UpdateFipStatsInfo(uint32_t fip, uint32_t id, Agent *agent);
     632        2462 :     const boost::uuids::uuid &uuid() const { return uuid_; }
     633         189 :     const boost::uuids::uuid &egress_uuid() const { return egress_uuid_;}
     634         555 :     const std::string &sg_rule_uuid() const {
     635         555 :         return data_.match_p.sg_policy.rule_uuid_;
     636             :     }
     637         555 :     const std::string &nw_ace_uuid() const { return nw_ace_uuid_; }
     638             :     const std::string fw_policy_name_uuid() const;
     639             :     const std::string fw_policy_uuid() const;
     640             :     const std::string RemotePrefix() const;
     641             :     const TagList &remote_tagset() const;
     642             :     const TagList &local_tagset() const;
     643          76 :     const std::string &peer_vrouter() const { return peer_vrouter_; }
     644          96 :     TunnelType tunnel_type() const { return tunnel_type_; }
     645             : 
     646           0 :     uint16_t short_flow_reason() const { return short_flow_reason_; }
     647             :     const MacAddress &smac() const { return data_.smac; }
     648             :     const MacAddress &dmac() const { return data_.dmac; }
     649         367 :     bool on_tree() const { return on_tree_; }
     650         144 :     void set_on_tree() { on_tree_ = true; }
     651        3958 :     std::mutex &mutex() { return mutex_; }
     652             : 
     653        2118 :     const Interface *intf_entry() const { return data_.intf_entry.get(); }
     654         952 :     const VnEntry *vn_entry() const { return data_.vn_entry.get(); }
     655         112 :     VmFlowRef *in_vm_flow_ref() { return &(data_.in_vm_entry); }
     656             :     const VmEntry *in_vm_entry() const { return data_.in_vm_entry.vm(); }
     657             :     const VmEntry *out_vm_entry() const { return data_.out_vm_entry.vm(); }
     658         490 :     const NextHop *src_ip_nh() const { return data_.src_ip_nh.get(); }
     659         948 :     const NextHop *rpf_nh() const { return data_.rpf_nh.get(); }
     660          74 :     uint32_t GetEcmpIndex() const { return data_.component_nh_idx; }
     661           0 :     const uint32_t bgp_as_a_service_sport() const {
     662           0 :         if (is_flags_set(FlowEntry::BgpRouterService))
     663           0 :             return data_.bgp_as_a_service_sport;
     664           0 :         return 0;
     665             :     }
     666          10 :     const uint32_t bgp_as_a_service_dport() const {
     667          10 :         if (is_flags_set(FlowEntry::BgpRouterService))
     668          10 :             return data_.bgp_as_a_service_dport;
     669           0 :         return 0;
     670             :     }
     671        4331 :     const MatchPolicy &match_p() const { return data_.match_p; }
     672             : 
     673          11 :     bool ActionSet(TrafficAction::Action action) const {
     674          11 :         return ((data_.match_p.action_info.action &
     675          11 :                  (1 << action)) ? true : false);
     676             :     }
     677         251 :     bool ImplicitDenyFlow() const {
     678         251 :         return ((data_.match_p.action_info.action &
     679         251 :                  (1 << TrafficAction::IMPLICIT_DENY)) ? true : false);
     680             :     }
     681        1853 :     bool deleted() { return deleted_; }
     682             : 
     683         291 :     bool IsShortFlow() const { return is_flags_set(FlowEntry::ShortFlow); }
     684          15 :     bool IsEcmpFlow() const { return is_flags_set(FlowEntry::EcmpFlow); }
     685           0 :     bool IsNatFlow() const { return is_flags_set(FlowEntry::NatFlow); }
     686         104 :     bool IsIngressFlow() const { return is_flags_set(FlowEntry::IngressDir); }
     687             :     // Flow action routines
     688             :     void ResyncFlow();
     689             :     void RpfUpdate();
     690             :     bool ActionRecompute();
     691             :     bool DoPolicy();
     692             :     void MakeShortFlow(FlowShortReason reason);
     693             :     void SetMirrorVrfFromAction();
     694             :     void SetHbsInfofromAction();
     695             :     void SetVrfAssignEntry();
     696             :     void ComputeReflexiveAction();
     697             :     uint32_t MatchAcl(const PacketHeader &hdr,
     698             :                       MatchAclParamsList &acl, bool add_implicit_deny,
     699             :                       bool add_implicit_allow, FlowPolicyInfo *info);
     700             :     void ResetPolicy();
     701             : 
     702             :     void FillFlowInfo(FlowInfo &info) const;
     703             :     void GetPolicyInfo(const VnEntry *vn, const FlowEntry *rflow);
     704             :     void GetPolicyInfo(const FlowEntry *rflow);
     705             :     void GetPolicyInfo(const VnEntry *vn);
     706             :     void GetPolicyInfo();
     707             :     void UpdateL2RouteInfo();
     708             :     void GetVrfAssignAcl();
     709           0 :     void SetMirrorVrf(const uint32_t id) {data_.mirror_vrf = id;}
     710             : 
     711             :     void GetPolicy(const VnEntry *vn, const FlowEntry *rflow);
     712             :     void GetNonLocalFlowSgList(const VmInterface *vm_port);
     713             :     void GetLocalFlowSgList(const VmInterface *vm_port,
     714             :                             const VmInterface *reverse_vm_port);
     715             :     void GetSgList(const Interface *intf);
     716             :     void GetApplicationPolicySet(const Interface *intf,
     717             :                                  const FlowEntry *rflow);
     718             :     void SetPacketHeader(PacketHeader *hdr);
     719             :     void SetOutPacketHeader(PacketHeader *hdr);
     720         224 :     void set_deleted(bool deleted) { deleted_ = deleted; }
     721             :     void SetAclAction(std::vector<AclAction> &acl_action_l) const;
     722             :     void UpdateReflexiveAction();
     723             :     bool IsFabricControlFlow() const;
     724             :     void SetAclFlowSandeshData(const AclDBEntry *acl,
     725             :                                FlowSandeshData &fe_sandesh_data,
     726             :                                Agent *agent) const;
     727             :     uint32_t InterfaceKeyToId(Agent *agent, const VmInterfaceKey &key);
     728           0 :     FlowTableKSyncEntry *ksync_entry() { return ksync_entry_; }
     729         677 :     FlowStatsCollector* fsc() const {
     730         677 :         return fsc_;
     731             :     }
     732             : 
     733         288 :     void set_fsc(FlowStatsCollector *fsc) {
     734         288 :         fsc_ = fsc;
     735         288 :     }
     736             :     static std::string DropReasonStr(uint16_t reason);
     737             :     std::string KeyString() const;
     738             :     void SetEventSandeshData(SandeshFlowIndexInfo *info);
     739             :     void LogFlow(FlowEventLog::Event event, FlowTableKSyncEntry* ksync,
     740             :                  uint32_t flow_handle, uint8_t gen_id);
     741             :     void RevFlowDepInfo(RevFlowDepParams *params);
     742         455 :     uint32_t last_event() const { return last_event_; }
     743        1078 :     void set_last_event(uint32_t event) {
     744        1078 :         last_event_ = event;
     745        1078 :         e_history_.UpdateEvtHistory(event);
     746        1078 :     }
     747           0 :     uint8_t GetMaxRetryAttempts() { return flow_retry_attempts_; }
     748           0 :     void  IncrementRetrycount() { flow_retry_attempts_++;}
     749           0 :     void ResetRetryCount(){ flow_retry_attempts_ = 0; }
     750           6 :     bool IsOnUnresolvedList(){ return is_flow_on_unresolved_list;}
     751           0 :     void SetUnResolvedList(bool added){ is_flow_on_unresolved_list = added;}
     752         644 :     FlowPendingAction *GetPendingAction() { return &pending_actions_; }
     753         598 :     bool trace() const { return trace_; }
     754         224 :     void set_trace(bool val) { trace_ = val; }
     755             : 
     756         454 :     FlowMgmtRequest *flow_mgmt_request() const { return flow_mgmt_request_; }
     757         747 :     void set_flow_mgmt_request(FlowMgmtRequest *req) {
     758         747 :         flow_mgmt_request_ = req;
     759         747 :     }
     760             : 
     761         742 :     FlowEntryInfo *flow_mgmt_info() const { return flow_mgmt_info_.get(); }
     762             :     void set_flow_mgmt_info(FlowEntryInfo *info);
     763             :     void FillUveFwStatsInfo(FlowUveFwPolicyInfo *info, bool added) const;
     764             :     void FillUveVnAceInfo(FlowUveVnAcePolicyInfo *info) const;
     765             :     bool IsClientFlow();
     766             :     bool IsServerFlow();
     767         230 :     uint16_t allocated_port() {
     768         230 :         return data_.allocated_port_;
     769             :     }
     770          80 :     void IncrementTransactionId() { transaction_id_++;}
     771        1057 :     uint32_t GetTransactionId() {return transaction_id_;}
     772         313 :     void SetHbsInterface (HbsInterface intf) { hbs_intf_ = intf; }
     773          22 :     HbsInterface GetHbsInterface() { return hbs_intf_; }
     774             : private:
     775             :     friend class FlowTable;
     776             :     friend class FlowEntryFreeList;
     777             :     friend class FlowStatsCollector;
     778             :     friend class KSyncFlowIndexManager;
     779             : 
     780             :     friend void intrusive_ptr_add_ref(FlowEntry *fe);
     781             :     friend void intrusive_ptr_release(FlowEntry *fe);
     782             : 
     783             :     void FillUveLocalRevFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added)
     784             :         const;
     785             :     void FillUveFwdFlowStatsInfo(FlowUveFwPolicyInfo *info, bool added) const;
     786             :     void RpfInit(const AgentRoute *rt, const IpAddress &sip);
     787             :     void RpfSetRpfNhFields(const NextHop *rpf_nh);
     788             :     void RpfSetRpfNhFields(const AgentRoute *rt, const NextHop *rpf_nh);
     789             :     void RpfSetSrcIpNhFields(const AgentRoute *rt, const NextHop *src_ip_nh);
     790             :     bool RpfFromSrcIpNh() const;
     791             :     void RpfComputeEgress();
     792             :     void RpfComputeIngress();
     793             : 
     794             :     bool InitFlowCmn(const PktFlowInfo *info, const PktControlInfo *ctrl,
     795             :                      const PktControlInfo *rev_ctrl, FlowEntry *rflow);
     796             :     VmInterfaceKey InterfaceIdToKey(Agent *agent, uint32_t id);
     797             :     void GetSourceRouteInfo(const AgentRoute *rt);
     798             :     void GetDestRouteInfo(const AgentRoute *rt);
     799             :     const std::string InterfaceIdToVmCfgName(Agent *agent, uint32_t id);
     800             :     const VrfEntry *GetDestinationVrf() const;
     801             :     bool SetQosConfigIndex();
     802             :     void SetAclInfo(SessionPolicy *sp, SessionPolicy *rsp,
     803             :                     const FlowPolicyInfo &fwd_flow_info,
     804             :                     const FlowPolicyInfo &rev_flow_info, bool tcp_rev,
     805             :                     bool is_sg);
     806             :     void SessionMatch(SessionPolicy *sp, SessionPolicy *rsp, bool is_sg);
     807             :     void UpdateReflexiveAction(SessionPolicy *sp, SessionPolicy *rsp);
     808             :     const std::string BuildRemotePrefix(const FlowRouteRefMap &rt_list,
     809             :                                         uint32_t vr, const IpAddress &ip) const;
     810             :     uint8_t GetUnderlayGwIndex(uint32_t intf_in, const IpAddress &sip,
     811             :                                   const IpAddress &dip, uint8_t proto, uint16_t sport,
     812             :                                   uint16_t dport) const;
     813             : 
     814             :     FlowKey key_;
     815             :     FlowTable *flow_table_;
     816             :     FlowData data_;
     817             :     bool l3_flow_;
     818             :     uint8_t gen_id_;
     819             :     uint32_t flow_handle_;
     820             :     FlowEntryPtr reverse_flow_entry_;
     821             :     static std::atomic<int> alloc_count_;
     822             :     bool deleted_;
     823             :     uint32_t flags_;
     824             :     uint16_t short_flow_reason_;
     825             :     boost::uuids::uuid uuid_;
     826             :     boost::uuids::uuid egress_uuid_;
     827             :     std::string sg_rule_uuid_;
     828             :     std::string nw_ace_uuid_;
     829             :     //IP address of the src vrouter for egress flows and dst vrouter for
     830             :     //ingress flows. Used only during flow-export
     831             :     std::string peer_vrouter_;
     832             :     //Underlay IP protocol type. Used only during flow-export
     833             :     TunnelType tunnel_type_;
     834             :     // Is flow-entry on the tree
     835             :     bool on_tree_;
     836             :     // Following fields are required for FIP stats accounting
     837             :     uint32_t fip_;
     838             :     VmInterfaceKey fip_vmi_;
     839             :     // Ksync entry for the flow
     840             :     FlowTableKSyncEntry *ksync_entry_;
     841             :     // atomic refcount
     842             :     std::atomic<int> refcount_;
     843             :     std::mutex mutex_;
     844             :     boost::intrusive::list_member_hook<> free_list_node_;
     845             :     FlowStatsCollector *fsc_;
     846             :     uint32_t last_event_;
     847             :     bool trace_;
     848             :     boost::scoped_array<FlowEventLog> event_logs_;
     849             :     uint16_t event_log_index_;
     850             :     FlowPendingAction pending_actions_;
     851             :     static SecurityGroupList default_sg_list_;
     852             :     uint8_t flow_retry_attempts_;
     853             :     bool is_flow_on_unresolved_list;
     854             :     // flow_mgmt_request used for compressing events to flow-mgmt queue.
     855             :     // flow_mgmt_request_ is set when flow is enqueued to flow-mgmt queue. No
     856             :     // subsequent enqueues are done till this field is set. The request can be
     857             :     // updated with new values to reflect latest state
     858             :     FlowMgmtRequest *flow_mgmt_request_;
     859             : 
     860             :     // Field used by flow-mgmt module. Its stored here to optimize flow-mgmt
     861             :     // and avoid lookups
     862             :     FlowMgmtEntryInfoPtr flow_mgmt_info_;
     863             :     const std::string fw_policy_;
     864             :     // Transaction id is used to detect old/stale vrouter add-ack response for
     865             :     // reverse flow handle allocation requests. It can happen if flow are
     866             :     // evicted from vrouter just after add-ack response sent to agent
     867             :     // and same flows are created before add-ack response gets processed
     868             :     // in agent.
     869             :     // transaction id should not be copied, it is incremented when flow entry
     870             :     // is reused.
     871             :     uint32_t transaction_id_;
     872             :     class FlowEntryEventHistory {
     873             :         public:
     874       10000 :             FlowEntryEventHistory() {
     875       10000 :                 idx_ = 0;
     876       60000 :                 for (uint32_t i = 0; i < size_; i++) {
     877       50000 :                       last_events_[i] = 0;
     878             :                 }
     879       10000 :             }
     880             : 
     881        1078 :             void UpdateEvtHistory( uint32_t event ) {
     882        1078 :                 last_events_[idx_] = event;
     883        1078 :                 idx_ = (idx_+1) % size_;
     884        1078 :             }
     885             : 
     886             :         private:
     887             :             static const uint32_t size_ = 5;
     888             :             uint32_t last_events_[size_];
     889             :             uint32_t idx_;
     890             :     };
     891             :     // Not modifying on Reset and Copy to retain the history
     892             :     FlowEntryEventHistory e_history_;
     893             :     HbsInterface          hbs_intf_;
     894             :     // IMPORTANT: Remember to update Reset() routine if new fields are added
     895             :     // IMPORTANT: Remember to update Copy() routine if new fields are added
     896             : };
     897             : 
     898             : void intrusive_ptr_add_ref(FlowEntry *fe);
     899             : void intrusive_ptr_release(FlowEntry *fe);
     900             : 
     901             : //A bound source port could be reused across different
     902             : //destination IP address, Port class holds a list of
     903             : //destination IP which have used this particular source
     904             : //port
     905             : class Port {
     906             : public:
     907             :     Port() :
     908             :         port_(0) {}
     909           0 :     Port(uint16_t port) : port_(port) {}
     910           0 :     ~Port() {}
     911             : 
     912           0 :     uint16_t port() const {
     913           0 :         return port_;
     914             :     }
     915             : 
     916             :     virtual uint16_t Bind() = 0;
     917             : protected:
     918             :     uint16_t port_;
     919             : };
     920             : 
     921             : class TcpPort : public Port {
     922             : public:
     923           0 :     TcpPort(boost::asio::io_context &io, uint16_t port):
     924           0 :         Port(port), socket_(io) {}
     925             :     virtual ~TcpPort();
     926             : 
     927             :     virtual uint16_t Bind();
     928             : private:
     929             :     boost::asio::ip::tcp::socket socket_;
     930             : };
     931             : 
     932             : class UdpPort : public Port {
     933             : public:
     934           0 :     UdpPort(boost::asio::io_context &io, uint16_t port):
     935           0 :         Port(port), socket_(io) {}
     936             :     virtual ~UdpPort();
     937             : 
     938             :     virtual uint16_t Bind();
     939             : private:
     940             :     boost::asio::ip::udp::socket socket_;
     941             : };
     942             : 
     943             : //Given a flow key gives the port used
     944             : //This would fail on first attempt or if the
     945             : //flow has been idle for long time
     946             : class PortCacheEntry {
     947             : public:
     948           0 :     PortCacheEntry(const FlowKey &key,
     949           0 :                    const uint16_t port):
     950           0 :         key_(key), port_(port), stale_(false) {}
     951             : 
     952           0 :     const FlowKey& key() const {
     953           0 :         return key_;
     954             :     }
     955             : 
     956           0 :     uint16_t port() const {
     957           0 :         return port_;
     958             :     }
     959             : 
     960           0 :     void set_stale(bool stale) const {
     961           0 :         stale_ = stale;
     962           0 :     }
     963             : 
     964             :     void MarkDelete() const;
     965             :     bool operator<(const PortCacheEntry &rhs) const;
     966             :     bool CanBeAged(uint64_t current_time, uint64_t timeout) const;
     967             : private:
     968             :     FlowKey  key_;
     969             :     uint16_t port_;
     970             :     mutable bool stale_;
     971             :     mutable uint64_t delete_time_;
     972             : };
     973             : 
     974             : class PortTable;
     975             : 
     976             : //Maintain a cache table which would be used to check
     977             : //if a flow prexisted and reuse the port if yes
     978             : class PortCacheTable {
     979             : public:
     980             :     static const uint64_t kCacheAging = 1000;
     981             :     static const uint64_t kAgingTimeout = 1000 * 1000 * 600; //10 minutes
     982             : 
     983             :     typedef std::set<PortCacheEntry> PortCacheEntryList;
     984             :     typedef std::map<uint16_t , PortCacheEntryList> PortCacheTree;
     985             : 
     986             :     PortCacheTable(PortTable *table);
     987             :     ~PortCacheTable();
     988             : 
     989             :     void Add(const PortCacheEntry &cache_entry);
     990             :     void Delete(const PortCacheEntry &cache_entry);
     991             :     const PortCacheEntry* Find(const FlowKey &key) const;
     992             :     void MarkDelete(const PortCacheEntry &cache_entry);
     993             : 
     994           2 :     void set_timeout(uint64_t timeout) {
     995           2 :         timeout_ = timeout;
     996           2 :     }
     997             : 
     998             : private:
     999             :     void StartTimer();
    1000             :     void StopTimer();
    1001             :     bool Age();
    1002             : 
    1003             :     PortCacheTree tree_;
    1004             :     PortTable *port_table_;
    1005             :     Timer* timer_;
    1006             :     uint16_t hash_;
    1007             :     uint64_t timeout_;
    1008             : };
    1009             : 
    1010             : //Per protocol table to manage port allocation
    1011             : class PortTable {
    1012             : public:
    1013             :     const static uint8_t kInvalidPort = 0;
    1014             : 
    1015             :     typedef boost::shared_ptr<Port> PortPtr;
    1016             :     typedef IndexVector<PortPtr> PortList;
    1017             : 
    1018             :     typedef std::map<uint16_t, uint16_t> PortToBitIndexMap;
    1019             :     typedef std::pair<uint16_t, uint16_t> PortToBitIndexPair;
    1020             : 
    1021             :     typedef IndexVector<FlowKey> PortBitMap;
    1022             :     typedef boost::shared_ptr<PortBitMap> PortBitMapPtr;
    1023             :     typedef std::vector<PortBitMapPtr> PortHashTable;
    1024             : 
    1025             :     PortTable(Agent *agent, uint32_t bucket_size, uint8_t protocol);
    1026             :     ~PortTable();
    1027             : 
    1028             :     uint16_t Allocate(const FlowKey &key);
    1029             :     void Free(const FlowKey &key, uint16_t port, bool release);
    1030             :     uint16_t HashFlowKey(const FlowKey &key);
    1031             : 
    1032           4 :     Agent *agent() {
    1033           4 :         return agent_;
    1034             :     }
    1035             : 
    1036             :     uint16_t port_count() const {
    1037             :         return port_config_.port_count;
    1038             :     }
    1039             : 
    1040           2 :     void set_timeout(uint64_t timeout) {
    1041           2 :         cache_.set_timeout(timeout);
    1042           2 :     }
    1043             : 
    1044           0 :     std::recursive_mutex& mutex() {
    1045           0 :         return mutex_;
    1046             :     }
    1047             : 
    1048             :     void UpdatePortConfig(const PortConfig *port_config);
    1049             : 
    1050             :     uint16_t GetPortIndex(uint16_t port) const;
    1051           0 :     const PortConfig* port_config() const {
    1052           0 :         return &port_config_;
    1053             :     }
    1054             : 
    1055           0 :     std::vector<uint16_t> GetPortList() const {
    1056           0 :         std::lock_guard<std::recursive_mutex> lock(mutex_);
    1057           0 :         std::vector<uint16_t> port_list;
    1058           0 :         PortToBitIndexMap::const_iterator it = port_to_bit_index_.begin();
    1059           0 :         for(; it != port_to_bit_index_.end(); it++) {
    1060           0 :             port_list.push_back(it->first);
    1061             :         }
    1062           0 :         return port_list;
    1063           0 :     }
    1064             : 
    1065             :     void GetFlowKeyList(uint16_t port, std::vector<FlowKey> &key) const;
    1066             : private:
    1067             :     Agent *agent_;
    1068             :     PortPtr CreatePortEntry(uint16_t port_no);
    1069             :     //Create a port with given port_no
    1070             :     void AddPort(uint16_t port_no);
    1071             :     void DeletePort(uint16_t port_no);
    1072             :     void Relocate(uint16_t port_no);
    1073             :     bool IsValidPort(uint16_t port, uint16_t count);
    1074             :     void DeleteAllFlow(uint16_t port, uint16_t index);
    1075             :     bool HandlePortConfig(const PortConfig &pc);
    1076             : 
    1077             :     uint8_t protocol_;
    1078             :     //Holds freed bit entry in table for while so that
    1079             :     //flow could be re-established after aging
    1080             :     PortCacheTable cache_;
    1081             : 
    1082             :     //Max no of hash entries, higher the number
    1083             :     //lesser the chance of clash. Hash would be derived based on
    1084             :     //destination IP and port
    1085             :     uint16_t hash_table_size_;
    1086             : 
    1087             :     //A Given a hash holds a list of used port numbers
    1088             :     //Free Bit index is to be used in Port tree to get actual port value
    1089             :     PortHashTable hash_table_;
    1090             : 
    1091             :     //Mapping from bit vector offset to actual port number
    1092             :     PortList port_list_;
    1093             : 
    1094             :     //Mapping from port to bit index for easier auditing on config
    1095             :     //change
    1096             :     PortToBitIndexMap port_to_bit_index_;
    1097             : 
    1098             :     //Number of port that agent can bind on
    1099             :     PortConfig port_config_;
    1100             :     mutable std::recursive_mutex mutex_;
    1101             :     std::unique_ptr<TaskTrigger> task_trigger_;
    1102             : };
    1103             : 
    1104             : class PortTableManager {
    1105             : public:
    1106             :     typedef boost::shared_ptr<PortTable> PortTablePtr;
    1107             :     PortTableManager(Agent *agent, uint16_t hash_table_size);
    1108             :     ~PortTableManager();
    1109             : 
    1110             :     uint16_t Allocate(const FlowKey &key);
    1111             :     void Free(const FlowKey &key, uint16_t port, bool release);
    1112             : 
    1113             :     void UpdatePortConfig(uint8_t protocol, const PortConfig *config);
    1114             :     static void PortConfigHandler(Agent *agent, uint8_t protocol,
    1115             :                                   const PortConfig *pc);
    1116           0 :     const PortTable* GetPortTable(uint8_t proto) {
    1117           0 :         return port_table_list_[proto].get();
    1118             :     }
    1119             : private:
    1120             :     Agent *agent_;
    1121             :     PortTablePtr port_table_list_[IPPROTO_MAX];
    1122             : };
    1123             : #endif //  __AGENT_PKT_FLOW_ENTRY_H__

Generated by: LCOV version 1.14