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: 131 196 66.8 %
Date: 2026-06-11 01:56:02 Functions: 69 94 73.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14