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 2306 : RevFlowDepParams() : rev_uuid_(), rev_egress_uuid_(), sip_(), vmi_uuid_(),
69 2306 : sg_uuid_(), vm_cfg_name_(), drop_reason_(),
70 2306 : nw_ace_uuid_(), action_info_() {
71 2306 : }
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 11088 : FlowKey() :
129 11088 : family(Address::UNSPEC), nh(0), src_addr(Ip4Address(0)),
130 11088 : dst_addr(Ip4Address(0)), protocol(0),
131 11088 : src_port(0), dst_port(0){
132 11088 : }
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 2448 : const FlowKey &key() const { return key_;}
595 4718 : FlowData &data() { return data_;}
596 78 : const FlowData &data() const { return data_;}
597 4233 : FlowTable *flow_table() const { return flow_table_; }
598 877 : bool l3_flow() const { return l3_flow_; }
599 1010 : uint8_t gen_id() const { return gen_id_; }
600 1970 : uint32_t flow_handle() const { return flow_handle_; }
601 : void set_flow_handle(uint32_t flow_handle, uint8_t gen_id);
602 2458 : 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 28047 : bool is_flags_set(const FlowEntryFlags &flags) const {
611 28047 : 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 12 : 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 1790 : std::mutex &mutex() { return mutex_; }
651 :
652 935 : 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 1842 : 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__
|